import pandas as pd
from typing import List

class ScriptGenerator:
    def __init__(self):
        self.vocabulary = [{}] * 4
        self._load_vocabulary()
        pass

    def _load_vocabulary(self):
        self._aliases = pd.read_csv('./aliases.csv', index_col='Alias')
        self._speech_converts = pd.read_csv('./speech_converts.csv')
        self._pacenotes = pd.read_csv('./pacenotes.csv', index_col='Id')
        self._word_corrections = pd.read_csv('./word_corrections.csv')

        # loop through each row in the aliases
        for index, row in self._aliases.iterrows():
            # split 'Speech' column by '|' and then get each part word count, store to vocabulary: word_count as key,
            # value is a dict, with words as key, and 'Alias' column as value
            parts = row['Speech'].split('|')
            for words in parts:
                word_count = len(words.split(' '))
                # vocabulary[word_count][words] should be the index of the row
                self.vocabulary[word_count-1][words] = index

        # loop through each row in the speech_converts
        for index, row in self._speech_converts.iterrows():
            word_count = len(row['speech'].split(' '))
            self.vocabulary[word_count-1][row['speech']] = row['pacenote']

        pass


    def generate_pacenote_for_line(self, line: str) -> str:
        original_line = line
        # trim line start and end
        line = line.strip()
        line = line.lower()
        line = line.replace(',', ' ')
        line = line.replace('?', '')
        line = line.replace('.', '')
        # line = line.replace('-', ' ')
        line = line.replace('  ', ' ')
        # replace word correction
        for index, row in self._word_corrections.iterrows():
            line = line.replace(row['word'], row['correction'])
        # split line by '>' to get the 1st part as distance
        parts = line.split('>')
        distance = float(parts[0].strip())
        # split the 2nd part by ' '
        words = parts[1].split(' ')
        while '' in words:
            words.remove('')
        # loop through words, in slide window, for each step, change the window size from 4 words to 1 word, check if it's in the vocabulary
        # if in, replace the word with the alias
        # if not, continue
        cur = 0
        result = []
        while cur < len(words):
            wordLen = min(4, len(words) - cur)
            while wordLen > 0:
                word = ' '.join(words[cur:cur + wordLen])
                if word in self.vocabulary[wordLen-1]:
                    if '|' in self.vocabulary[wordLen-1][word]:
                        for part in self.vocabulary[wordLen-1][word].split('|'):
                            result.append(part)
                    else:
                        result.append(self.vocabulary[wordLen-1][word])
                    cur += wordLen
                    break
                else:
                    wordLen -= 1
            if wordLen == 0:
                result.append(words[cur])
                cur += 1

        result_str = ''
        for i in range(len(result)):
            word = result[i]
            if word in self._aliases.index:
                token = self._aliases.loc[word]['Token']
                if i != 0:
                    is_modifier = self._pacenotes.loc[token]['CanBeModifier']
                    if is_modifier == 1:
                        result_str += '/' + word
                    else:
                        result_str += ',' + word
                else:
                    result_str += ',' + word
            else:
                result_str += '!' + word

        return str(int(distance)) + result_str + '\t#' + original_line


if __name__ == '__main__':
    generator = ScriptGenerator()
    # read from example.txt as lines
    lines = []
    with open('./example.txt') as f:
        lines = f.readlines()

    for line in lines:
        print(generator.generate_pacenote_for_line(line), end='')
    
    print()

    line = '-599>and left of a crest, 40.'
    print(generator.generate_pacenote_for_line(line))

